package com.leyou.gateway.filters;

import com.leyou.common.auth.entity.Payload;
import com.leyou.common.auth.entity.UserInfo;
import com.leyou.common.auth.utils.JwtUtils;
import com.leyou.common.utils.CookieUtils;
import com.leyou.gateway.config.FilterProperties;
import com.leyou.gateway.config.JwtProperties;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * @Auther: xiang
 * @Date: 2019/8/31 15:17
 * @Description:
 */
@Slf4j
@Component
@EnableConfigurationProperties({JwtProperties.class, FilterProperties.class})
public class AuthFilter extends ZuulFilter {

    @Autowired
    private JwtProperties prop;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private FilterProperties filter;


    /**
     * 过滤器类型
     *
     * @return
     */
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    /**
     * 过滤器的时机
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER + 1;
    }

    /**
     * 过滤器是否执行 true执行
     * flase不执行
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        // 1.获取上下文
        RequestContext ctx = RequestContext.getCurrentContext();
        // 2.获取request
        HttpServletRequest request = ctx.getRequest();
        // 3.获取请求路径
        String path = request.getRequestURI();
         //遍历白名单，并且判断该路径是否是白名单
        for (String s : filter.getAllowPaths()) {
            //如果该路径是以白名单开头，就返回false
           if (path.startsWith(s)){
               return false;
           }

        }
        return true;
    }

    /**
     * 过滤器执行的具体业务逻辑
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {


        //获取上下文
        RequestContext ctx = RequestContext.getCurrentContext();
        //获取request请求
        HttpServletRequest request = ctx.getRequest();
        try {
            //取出cookie以及cookie中的token
            String token = CookieUtils.getCookieValue(request, prop.getUser().getCookieName());
            Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token, prop.getPublicKey(), UserInfo.class);
            //校验黑名单
            Boolean boo = redisTemplate.hasKey(payload.getId());
            if (boo != null && boo) {
                throw new RuntimeException("token已经退出,无效token");
            }
            //权限校验
            UserInfo userInfo = payload.getUserInfo();

            //获得角色
            String role = userInfo.getRole();
            //获取当前资源路径
            String requestURI = request.getRequestURI();

            String method = request.getMethod();
            //判断权限
            log.info("【网关】用户{},角色{}。访问服务{} : {}，", userInfo.getUsername(), role, method, requestURI);
        } catch (RuntimeException e) {
            // 拦截请求
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(403);// Forbidden
            log.error("非法访问，未登录，地址：{}", request.getRemoteHost(), e);
        }
        return null;
    }
}